package com.hunan.api.catv.interceptor;

import com.hunan.api.catv.common.CacheKey;
import com.hunan.api.catv.common.CacheName;
import com.hunan.api.catv.common.Constants;
import com.hunan.api.catv.mq.MqConstants;
import com.hunan.api.catv.service.biz.mq.MqBiz;
import com.hunan.api.catv.service.biz.system.SystemDictBiz;
import com.hunan.api.catv.utils.GsonUtils;
import com.hunan.api.catv.utils.RedisUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.MessageFormat;
import java.util.*;

/**
 * @author jiang zhuan
 * @version 1.0
 * @description 描述
 * @date 2020/12/23 0023
 * @package com.hunan.api.catv.interceptor
 * @company 湖南有线
 */
public class MonitorMethodInterceptor extends HandlerInterceptorAdapter {
    private Logger log = LoggerFactory.getLogger(MonitorMethodInterceptor.class);

    @Autowired
    RedisUtils redisUtils;

    @Autowired
    MqBiz mqBiz;

    @Autowired
    SystemDictBiz systemDictBiz;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        long startTime = System.currentTimeMillis();
        request.setAttribute("log-startTime", startTime);
        //获取方法名
        String requestURI = request.getRequestURI();
        if (systemDictBiz.getStringByKey(Constants.monitor_interface_conf).contains(requestURI)) {
            String remoteIp = getRemoteIp(request);
            //查询该IP是否频繁访问该接口次数已达上限
            String format = MessageFormat.format("{0}-{1}", remoteIp, requestURI);
            String blockIp = (String) Optional.ofNullable(redisUtils.hget(CacheName.blockIp, format)).orElse(null);
            if (org.apache.commons.lang3.StringUtils.isNotBlank(blockIp)) {
                return true;
            }
            HashMap<String, Object> map = new HashMap<>(16);
            map.put("startTime", startTime / 1000);
            map.put("remoteIp", remoteIp);
            map.put("requestURI", requestURI);
            mqBiz.push(MqConstants.BLOCK_IP_EXCHANGE, MqConstants.BLOCK_IP_ROUTINGKEY, GsonUtils.toJson(map));
        }

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        try {
            String requestURI = request.getRequestURI();
            String requestType = request.getMethod();
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            String packageStr = handlerMethod.getBeanType().toString();
            String methodName = handlerMethod.getShortLogMessage();
            Map<String, String[]> parameterMap = Optional.ofNullable(request.getParameterMap()).orElse(new HashMap<>());
            StringBuilder params = new StringBuilder();
            Enumeration<String> headerNames = request.getHeaderNames();
            StringBuilder headers = new StringBuilder();
            while (headerNames.hasMoreElements()) {
                String h = headerNames.nextElement();
                headers.append(h + ":" + request.getHeader(h));
                headers.append(",");
            }

            for (Map.Entry<String, String[]> stringEntry : parameterMap.entrySet()) {
                params.append(stringEntry.getKey() + ":" + Arrays.toString(stringEntry.getValue()));
                params.append(",");
            }

            long startTime = (Long) request.getAttribute("log-startTime");
            long endTime = System.currentTimeMillis();
            long time = endTime - startTime;

            //获取Controller返回值
            Object body = request.getSession().getAttribute("log-body");
            String result = "";
            try {
                result = GsonUtils.toJson(body);
            } catch (Exception e) {
                log.info("GSON转换异常：{}", e);
            }
            log.info("[action operation requestIp:[{}] requestType:[{}] requestURI:[{}]  runningTime:[{}] package:[{}] method:[{}] params:[{}] requestHeader:[{}] return:[{}] userId:[{}]]", getRemoteIp(request), requestType, requestURI, time, packageStr, methodName, params.toString(), headers.toString(), result, getMemberIdV2(request));
        } catch (Exception e) {
            log.error("记录操作日志切面失败：{}", e);
        }


    }

    public Integer getMemberIdV2(HttpServletRequest request) {
        Object memberId = request.getAttribute("memberId");
        String token = request.getHeader("token");
        if (!ObjectUtils.isEmpty(memberId)) {
            return Integer.valueOf(memberId.toString());
        }
        if (!ObjectUtils.isEmpty(token)) {
            String memberKey = MessageFormat.format(CacheKey.memberToken, token);
            return (Integer) redisUtils.get(memberKey);
        }
        return null;
    }

    public String getRemoteIp(HttpServletRequest request) {
        if (!StringUtils.isEmpty(request.getParameter("clientIP"))) {
            return request.getParameter("clientIP");
        }
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip.split(",")[0];
    }


}
